package com.program.beautymakeup.aop;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSON;

import com.program.beautymakeup.common.OperLog;
import com.program.beautymakeup.domain.entity.Operlog;
import com.program.beautymakeup.domain.vo.ResultInfo;
import com.program.beautymakeup.mapper.OperlogMapper;
import com.program.beautymakeup.service.AsyncService;
import com.program.beautymakeup.utils.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 记录操作日志的切面
 *
 * @author CaiKe
 * @date 2021/11/13 18:08
 */
@Slf4j
@Aspect
@Component
public class OperLogAOP {

    @Autowired
    private AsyncService asyncService;
    @Autowired
    private OperlogMapper operlogMapper;
    /**
     * 正常操作日志切入点
     */
    @Pointcut("@annotation(com.program.beautymakeup.common.OperLog)")
    public void LogPointCut() {
    }

    /**
     * 方法正常返回时拦截用户操作日志（如果连接点抛出异常，则不执行）
     *
     * @param joinPoint
     * @param rs
     */
    @SuppressWarnings("rawtypes")
    @AfterReturning(value = "LogPointCut()", returning = "rs")
    public void SaveOperationLog(JoinPoint joinPoint, Object rs) {
        if (((ResultInfo) rs).getCode() != 200) {
            // 若非buildSuccess，则不记录日志
            return;
        }
        Operlog operLog = new Operlog();
        // 从切入点获取指定的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 设置方法信息
        val method = signature.getMethod();
        val clazz = joinPoint.getTarget().getClass();
        final String className = clazz.getName();
        operLog.setMethod(className + "::" + method.getName());
        // 从注解获取操作信息
        final OperLog operAnno = method.getAnnotation(OperLog.class);
                operLog.setModule(operAnno.module());
            operLog.setType(operAnno.type());
                operLog.setDescription(operAnno.description());
            // 设置出参信息(rawTypes)
            // 查询行为不保存返回信息
            if (operAnno.type() == 4)
                operLog.setRespParam("");
            else
                operLog.setRespParam(JSON.toJSONString(((ResultInfo) rs).getData()));
        // 设置请求参数信息
        operLog.setReqParam(JSON.toJSONString(joinPoint.getArgs()));
        operLog.setUserId(StpUtil.getLoginIdAsInt());
        operLog.setIp(RequestUtil.getIpAddress());
        operLog.setCreateTime(new Date());
        log.info(operLog.toString());
        asyncService.execute(() -> operlogMapper.insert(operLog));
    }


}